package com.taritari.journal.services;

import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.taritari.journal.entity.po.Journals;
import com.taritari.journal.entity.po.SdImg;
import com.taritari.journal.entity.vo.B64ImageVo;
import com.taritari.journal.entity.vo.ERNIEBotVo;
import com.taritari.journal.entity.vo.PromptAndDescVo;
import com.taritari.journal.entity.vo.SdVo;
import com.taritari.journal.mapper.JournalsMapper;
import com.taritari.journal.mapper.SdImgMapper;
import com.taritari.journal.services.impl.JournalsServiceImpl;
import com.taritari.journal.services.impl.SdImgServiceImpl;
import com.taritari.journal.utils.BaiDuApiUtil;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author taritari
 * @date 2024-04-21 14:05
 * @description
 */
@Slf4j
@Service
public class SdImgService extends ServiceImpl<SdImgMapper, SdImg> implements SdImgServiceImpl {
    @Autowired
    private SdImgMapper sdImgMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private BaiDuApiUtil baiDuApiUtil;

    /**
     * 通过prompt生成图像
     * */
    @Override
    public Map<String,String> generateImgByPrompt(SdImg sdImg) {
        // 查询今天是否已经生成过了
        QueryWrapper<SdImg> queryWrapper = new QueryWrapper<>();
        LocalDate currentDate = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String formattedDate = currentDate.format(formatter);
        queryWrapper.eq("author_id",sdImg.getAuthorId());
        queryWrapper.like("create_time",formattedDate);
        List<SdImg> sdImgs = sdImgMapper.selectList(queryWrapper);
        System.out.println(sdImgs);
        if (sdImgs.size() != 0){
            Map<String, String> ret = new HashMap<>();
            ret.put("desc","401");
            return ret;
        }
        Map<String, String> promptByContent = getPromptByContent(sdImg.getPrompt());
        return promptByContent;
    }
    /**
     * 添加
     * */
    @Override
    public long  addSdImg(SdImg sdImg) {
        long  insert = sdImgMapper.insertSdImg(sdImg.getPrompt(), sdImg.getImgUrl(),sdImg.getDesc(),sdImg.getAuthorId());
        return insert;
    }
    /**
     * 通过id查询
     * */
    @Override
    public Page<SdImg> getSdImgByPage(long currentPage, int authorId) {
        //分页参数
        Page<SdImg> rowPage = new Page(currentPage, 3);

        //queryWrapper组装查询where条件
        LambdaQueryWrapper<SdImg> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SdImg::getAuthorId,authorId);
        rowPage = this.baseMapper.selectPage(rowPage, queryWrapper);
        return rowPage;
    }

    /**
     * 获取prompt通过日记内容
     * */
    public Map<String,String> getPromptByContent(String content) {
        System.out.println(content);
        // 然后从redis获取百度api的token
        String accessToken = stringRedisTemplate.opsForValue().get("qianFanaccessToken");

        // m没有就重新获取
        if (StringUtil.isNullOrEmpty(accessToken)){
            accessToken = baiDuApiUtil.getQianFanToken();
        }
        //准备数据
        List<Map<String,String >> dataList = new ArrayList<>();
        Map<String,String> userContent = new HashMap<>(8);
        Map<String,Object> dataMap = new HashMap<>(8);
        userContent.put("role","user");
        //设置具体prompt
        StringBuffer messages = new StringBuffer("现在，你需要根据我传入的日记文字去构建一副对人有正向引导的图像，然后给我返回prompt(使用逗号分隔,使用英文单词)和图片描述(使用中文，内容为简洁的语言描述图像)。返回格式为:{\"prompt\":[],\"desc\":\"\"};严格按照返回格式返回，只需要构建一幅图，除了返回格式以外不要返回任何东西，以下这是我的日记列表内容:");
        messages.append(content);
        userContent.put("content",messages.toString());
        dataList.add(userContent);
        dataMap.put("messages",dataList);
        String jsonString = JSONObject.toJSONString(dataMap);
        ERNIEBotVo ernieBotVo = baiDuApiUtil.wenXinWorkShop(accessToken, jsonString);
        String commentContent = ernieBotVo.getResult();
        System.out.println(commentContent.substring(7, commentContent.length() - 4));
        // 使用Hutool的JSONUtil将字符串解析为JSONObject
        cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(commentContent.substring(7, commentContent.length() - 4));
        PromptAndDescVo promptAndDescVo = new PromptAndDescVo();
        promptAndDescVo=jsonObject.toBean(PromptAndDescVo.class);
        StringBuffer prompt = new StringBuffer();
        for (String s : promptAndDescVo.getPrompt()) {
            prompt.append(s).append(",");
        }
        String base64 = generateImg(prompt.toString());
        Map<String,String> retMap = new HashMap<>();
        retMap.put("base64",base64);
        retMap.put("desc",promptAndDescVo.getDesc());
        return retMap;
    }

    /**
     * 图像生成
     * @param prompt 图像描述
     * @return 图像base64编码
     * */
    public String generateImg(String prompt) {
//        String base64Image = sdGent(prompt);
        String url = "http://127.0.0.1:7860/sdapi/v1/txt2img";
        Map<String,Object> override_settings = new HashMap<>();
        override_settings.put("sd_model_checkpoint","pastelMixStylizedAnime_pastelMixPrunedFP16.safetensors");
        override_settings.put("CLIP_stop_at_last_layers",2);
        Map<String,Object> map = new HashMap<>();
        map.put("override_settings",override_settings);
        map.put("negative_prompt","negative_prompt");
        map.put("prompt","view,flower,"+prompt);
        map.put("steps",30);
        map.put("sampler_name","Euler a");
        map.put("width",512);
        map.put("height",512);
        map.put("batch_size",1);
        map.put("n_iter",1);
        map.put("seed",1);
        map.put("CLIP_stop_at_last_layers",2);
        map.put("restore_faces","False");
        String jsonStr = JSONUtil.toJsonStr(map);

        String result = HttpRequest.post(url)
                .body(jsonStr)
                .header("Content-Type", "application/json")
                .execute()
                .body();

        cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(result);
        JSONArray images = jsonObject.getJSONArray("images");
        String base64Image =  images.getStr(0);

        // 返回Base64编码的图片给前端
        return base64Image;
    }
    /**
     * sd文生图
     * */
    public String sdGent(String prompt) {

        // 然后从redis获取百度api的token
        String accessToken = stringRedisTemplate.opsForValue().get("qianFanaccessToken");
        // m没有就重新获取
        if (StringUtil.isNullOrEmpty(accessToken)){
            accessToken = baiDuApiUtil.getQianFanToken();
        }
        //准备数据
        List<Map<String,Object >> dataList = new ArrayList<>();
        Map<String,Object> dataMap = new HashMap<>(8);

        dataMap.put("prompt",prompt);
        dataMap.put("size","768x768");
        dataMap.put("n", 1);
        dataMap.put("steps", 20);
        dataMap.put("sampler_index","Euler a");
        String jsonString = JSONObject.toJSONString(dataMap);
        SdVo ernieBotVo = baiDuApiUtil.stableDiffusion(accessToken, jsonString);
        List<B64ImageVo> b64Data = ernieBotVo.getData();
        String b64Image = b64Data.get(0).getB64_image();

        return  b64Image;
    }
}
